package com.deer.wms.project.root.util;

import com.google.zxing.*;
import com.google.zxing.client.j2se.BufferedImageLuminanceSource;
import com.google.zxing.client.j2se.MatrixToImageWriter;
import com.google.zxing.common.BitMatrix;
import com.google.zxing.common.HybridBinarizer;
import com.google.zxing.qrcode.decoder.ErrorCorrectionLevel;
import sun.misc.BASE64Encoder;

import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.Objects;

public class BarCodeUtils {


    public static void main(String[] args) {
        String aaaa = encodeTiaoXingMa90("111111", 202, 50);

        System.out.println(aaaa);
    }

    // 生成二维码base64
    public static String encode(String contents, int width, int height) {
        Map<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        //设置二维码四周的留白
        hints.put(EncodeHintType.MARGIN, 2);
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);
        // 指定编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
            // MatrixToImageWriter.writeToStream(bitMatrix, "png", new FileOutputStream(imgPath));

            ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
            ImageIO.write(MatrixToImageWriter.toBufferedImage(bitMatrix), "png", baos);//写入流中
            byte[] bytes = baos.toByteArray();//转换成字节
            BASE64Encoder encoder = new BASE64Encoder();
            String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
            png_base64 = "data:image/png;base64," + png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
            return png_base64;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    // 生成二维码

    public String encode(String contents, int width, int height, String imgPath) {
        Map<EncodeHintType, Object> hints = new Hashtable<EncodeHintType, Object>();
        // 指定纠错等级
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.L);
        // 指定编码格式
        hints.put(EncodeHintType.CHARACTER_SET, "UTF8");
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.QR_CODE, width, height, hints);
            MatrixToImageWriter.writeToStream(bitMatrix, "png", new FileOutputStream(imgPath));

            ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
            ImageIO.write(MatrixToImageWriter.toBufferedImage(bitMatrix), "png", baos);//写入流中
            byte[] bytes = baos.toByteArray();//转换成字节
            BASE64Encoder encoder = new BASE64Encoder();
            String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
            png_base64 = png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
            return png_base64;
        } catch (Exception e) {

            e.printStackTrace();

        }
        return null;
    }

    // 二维码解析

    public String decode(String imgPath) {
        BufferedImage image = null;
        Result result = null;
        try {
            image = ImageIO.read(new File(imgPath));
            if (image == null) {
                System.out.println("the decode image may be not exit.");
            }
            LuminanceSource source = new BufferedImageLuminanceSource(image);
            BinaryBitmap bitmap = new BinaryBitmap(new HybridBinarizer(source));
            Map<DecodeHintType, Object> hints = new Hashtable<DecodeHintType, Object>();
            hints.put(DecodeHintType.CHARACTER_SET, "UTF8");
            result = new MultiFormatReader().decode(bitmap, hints);
            return result.getText();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String encodeTiaoXingMa90(String contents, int width, int height) {
        int codeWidth = 3 + // start guard
                (7 * 6) + // left bars
                5 + // middle guard
                (7 * 6) + // right bars
                3; // end guard
        codeWidth = Math.max(codeWidth, width);
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, codeWidth, height, null);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
            ImageIO.write(Rotate(MatrixToImageWriter.toBufferedImage(bitMatrix), 90), "png", baos);//写入流中
            byte[] bytes = baos.toByteArray();//转换成字节
            BASE64Encoder encoder = new BASE64Encoder();
            String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
            png_base64 = "data:image/png;base64," + png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
            return png_base64;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    public static String encodeTiaoXingMa(String contents, int width, int height) {
        int codeWidth = 3 + // start guard
                (7 * 6) + // left bars
                5 + // middle guard
                (7 * 6) + // right bars
                3; // end guard
        codeWidth = Math.max(codeWidth, width);
        //定义二维码参数
        Map<EncodeHintType, Object> hints = new HashMap<>();

        hints.put(EncodeHintType.CHARACTER_SET, "utf-8");//设置编码
        hints.put(EncodeHintType.ERROR_CORRECTION, ErrorCorrectionLevel.Q);//设置容错等级
        hints.put(EncodeHintType.MARGIN, 2);//设置边距默认是5
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.CODE_128, codeWidth, height, hints);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();//io流
            ImageIO.write(MatrixToImageWriter.toBufferedImage(bitMatrix), "png", baos);//写入流中
            byte[] bytes = baos.toByteArray();//转换成字节
            BASE64Encoder encoder = new BASE64Encoder();
            String png_base64 = encoder.encodeBuffer(bytes).trim();//转换成base64串
            png_base64 = "data:image/png;base64," + png_base64.replaceAll("\n", "").replaceAll("\r", "");//删除 \r\n
            return png_base64;

        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }


    // 条形码生成

    public void encodeTiaoXingMa(String contents, int width, int height, String imgPath) {
        int codeWidth = 3 + // start guard
                (7 * 6) + // left bars
                5 + // middle guard
                (7 * 6) + // right bars
                3; // end guard
        codeWidth = Math.max(codeWidth, width);
        try {
            BitMatrix bitMatrix = new MultiFormatWriter().encode(contents, BarcodeFormat.EAN_13, codeWidth, height, null);

            MatrixToImageWriter.writeToStream(bitMatrix, "png", new FileOutputStream(imgPath));
        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    /**
     * 网络图片转换Base64的方法
     *
     * @param netImagePath
     */
    private static void NetImageToBase64(String netImagePath) {
        final ByteArrayOutputStream data = new ByteArrayOutputStream();
        try {
            // 创建URL
            URL url = new URL(netImagePath);
            final byte[] by = new byte[1024];
            // 创建链接
            final HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);

            new Thread(new Runnable() {
                @Override
                public void run() {
                    try {
                        InputStream is = conn.getInputStream();
                        // 将内容读取内存中
                        int len = -1;
                        while ((len = is.read(by)) != -1) {
                            data.write(by, 0, len);
                        }
                        // 对字节数组Base64编码
                        BASE64Encoder encoder = new BASE64Encoder();
                        String strNetImageToBase64 = encoder.encode(data.toByteArray());
                        System.out.println("网络图片转换Base64:" + strNetImageToBase64);
                        // 关闭流
                        is.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();

        } catch (IOException e) {
            e.printStackTrace();
        }
    }


    /**
     * 本地图片转换Base64的方法
     *
     * @param imgPath
     */

    private static void ImageToBase64(String imgPath) throws IOException {
        InputStream in = null;
        byte[] data = null;
        // 读取图片字节数组
        try {
            in = new FileInputStream(imgPath);
            data = new byte[in.available()];
//            in.read(data);
            in.close();
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            Objects.requireNonNull(in).close();
        }
        // 对字节数组Base64编码
        BASE64Encoder encoder = new BASE64Encoder();
        // 返回Base64编码过的字节数组字符串
        System.out.println("本地图片转换Base64:" + encoder.encode(Objects.requireNonNull(data)));
    }


    /**
     * 图像旋转
     *
     * @param src
     * @param angel
     * @return
     */
    public static BufferedImage Rotate(Image src, double angel) {
        int src_width = src.getWidth(null);
        int src_height = src.getHeight(null);
        // calculate the new image size

        String aaa = CalcRotatedSize(src_height, src_width, angel);
        String[] bbb = aaa.split("-");
        String strWidth = bbb[0];
        String strHeight = bbb[1];
        Integer desWidth = Integer.parseInt(strWidth);


        Integer desHeight = Integer.parseInt(strHeight);
        BufferedImage res = null;
        res = new BufferedImage(desWidth, desHeight,
                BufferedImage.TYPE_3BYTE_BGR);
        Graphics2D g2 = res.createGraphics();
        // transform
        g2.translate((desWidth - src_width) / 2,
                (desHeight - src_height) / 2);
        g2.rotate(Math.toRadians(angel), src_width >> 1, src_height >> 1);

        g2.drawImage(src, null, null);
        return res;
    }

    public static String CalcRotatedSize(int srcHeight, int srcWidth, double angel) {
        // if angel is greater than 90 degree, we need to do some conversion
        if (angel >= 90) {
            if (angel / 90 % 2 == 1) {
                int temp = srcHeight;
                srcHeight = srcWidth;
                srcWidth = temp;
            }
            angel = angel % 90;
        }

        double srcH = (double) srcHeight;
        double srcW = (double) srcWidth;

        double r = Math.sqrt(srcH * srcH + srcW * srcW) / 2L;
        double len = 2 * Math.sin(Math.toRadians(angel) / 2) * r;
        double angel_alpha = (Math.PI - Math.toRadians(angel)) / 2;
        double angel_dalta_width = Math.atan((double) srcHeight / srcWidth);
        double angel_dalta_height = Math.atan((double) srcWidth / srcHeight);

        int len_dalta_width = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_width));
        len_dalta_width = len_dalta_width > 0 ? len_dalta_width : -len_dalta_width;

        int len_dalta_height = (int) (len * Math.cos(Math.PI - angel_alpha
                - angel_dalta_height));
        len_dalta_height = len_dalta_height > 0 ? len_dalta_height : -len_dalta_height;

        int des_width = srcWidth + len_dalta_width * 2;
        int des_height = srcHeight + len_dalta_height * 2;
        des_width = des_width > 0 ? des_width : -des_width;
        des_height = des_height > 0 ? des_height : -des_height;
        return des_width + "-" + des_height;
        // return new java.awt.Rectangle(new Dimension(des_width, des_height));
    }
}
